// safe project safe.go
package safe

//协程安全包，map操作都已经加了锁
//实现了两种类型Map 一个是数字Map 一个是字符串Map

import (
	"log"
	"reflect"
	"sync"
)

////////////////////////////////////////////////////////////////////////////////
type StringMap struct {
	m    map[string]interface{}
	lock *sync.RWMutex
}

//新建一个字符串的Map
func NewStringMap() *StringMap {
	m := new(StringMap)
	m.Init()
	return m
}

//Map 基础数据初始化
func (this *StringMap) Init() {
	this.lock = new(sync.RWMutex)
	this.m = map[string]interface{}{}
}

//获取Map的数据个数
func (this *StringMap) Size() int {
	this.lock.RLock()
	defer this.lock.RUnlock()
	return len(this.m)
}

//Map 复位 （清空数据）
func (this *StringMap) Reset() {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.m = map[string]interface{}{}
}

//查找给定关键字的值
func (this *StringMap) Find(key string) (interface{}, bool) {
	this.lock.RLock()
	defer this.lock.RUnlock()
	if point, ok := this.m[key]; ok {
		return point, true
	}
	return nil, false
}

//这个函数只支持基本数据类型
//查找给定关键字的值， 并存放到 val中
//val 必须是一个指针的地址
//类似于c的**val
func (this *StringMap) Get(key string, val interface{}) bool {
	if val == nil {
		return false
	}

	//只有传递的参数是指针类型才可以继续
	sv := reflect.ValueOf(val)
	if sv.Kind() != reflect.Ptr {
		return false
	}

	v, b := this.Find(key)
	if !b {
		return false
	}

	//获取指针地址指向的内容 val:**value  sv:*value
	sv = sv.Elem()

	vv := reflect.ValueOf(v)

	switch sv.Type().Kind() {
	case reflect.Bool:
		sv.Set(vv)
		return true
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		switch vv.Type().Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			sv.SetInt(vv.Int())
			return true
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		switch vv.Type().Kind() {
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			sv.SetUint(vv.Uint())
			return true
		}
	case reflect.Float32:
		if vv.Type().Kind() == reflect.Float32 {
			sv.Set(vv)
			return true
		}
	case reflect.Float64:
		if vv.Type().Kind() == reflect.Float64 {
			sv.Set(vv)
			return true
		}
	default:
		//其他类型
		if sv.Type().String() == vv.Type().String() {
			sv.Set(vv)
			return true
		} else {
			log.Println("paramter value:", sv.Type().String(), "map value:", vv.Type().String())
		}
	}

	return false
}

//指定Map指定关键字的值
func (this *StringMap) Set(key string, value interface{}) {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.m[key] = value
	return
}

//删除Map中的一个值
func (this *StringMap) Delete(key string) {
	this.lock.Lock()
	defer this.lock.Unlock()
	delete(this.m, key)
}

//删除Map中的一个值
func (this *StringMap) Remove(key string) {
	this.lock.Lock()
	defer this.lock.Unlock()
	delete(this.m, key)
}

//获取Map中全部的关键字列表
func (this *StringMap) Keys() []string {
	this.lock.RLock()
	defer this.lock.RUnlock()
	keys := make([]string, 0, len(this.m))
	for key, _ := range this.m {
		keys = append(keys, key)
	}
	return keys
}

//获取Map中全部值列表
func (this *StringMap) Values() []interface{} {
	this.lock.RLock()
	defer this.lock.RUnlock()
	vals := make([]interface{}, 0, len(this.m))
	for _, val := range this.m {
		vals = append(vals, val)
	}
	return vals
}

//获取Map中键值对列表
func (this *StringMap) KeyValues() (keys []string, vals []interface{}) {
	this.lock.RLock()
	defer this.lock.RUnlock()
	keys = make([]string, 0, len(this.m))
	vals = make([]interface{}, 0, len(keys))
	for key, val := range this.m {
		keys = append(keys, key)
		vals = append(vals, val)
	}
	return
}

////////////////////////////////////////////////////////////////////////////////
type Int64Map struct {
	m    map[int64]interface{}
	lock *sync.RWMutex
}

//新建一个字符串的Map
func NewInt64Map() *Int64Map {
	m := new(Int64Map)
	m.Init()
	return m
}

//Map 基础数据初始化
func (this *Int64Map) Init() {
	this.lock = new(sync.RWMutex)
	this.m = map[int64]interface{}{}
}

//获取Map的数据个数
func (this *Int64Map) Size() int {
	this.lock.RLock()
	defer this.lock.RUnlock()
	return len(this.m)
}

//Map 复位 （清空数据）
func (this *Int64Map) Reset() {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.m = map[int64]interface{}{}
}

//查找给定关键字的值
func (this *Int64Map) Find(key int64) (interface{}, bool) {
	this.lock.RLock()
	defer this.lock.RUnlock()
	if point, ok := this.m[key]; ok {
		return point, true
	}
	return nil, false
}

//查找给定关键字的值， 并存放到 val中
//val 必须是一个指针的地址
//类似于c的**val
func (this *Int64Map) Get(key int64, val interface{}) bool {
	if val == nil {
		return false
	}

	//只有传递的参数是指针类型才可以继续
	sv := reflect.ValueOf(val)
	if sv.Kind() != reflect.Ptr {
		return false
	}

	v, b := this.Find(key)
	if !b {
		return false
	}

	//获取指针地址指向的内容 val:**value  sv:*value
	sv = sv.Elem()

	vv := reflect.ValueOf(v)

	switch sv.Type().Kind() {
	case reflect.Bool:
		sv.Set(vv)
		return true
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		switch vv.Type().Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			sv.SetInt(vv.Int())
			return true
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		switch vv.Type().Kind() {
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			sv.SetUint(vv.Uint())
			return true
		}
	case reflect.Float32:
		if vv.Type().Kind() == reflect.Float32 {
			sv.Set(vv)
			return true
		}
	case reflect.Float64:
		if vv.Type().Kind() == reflect.Float64 {
			sv.Set(vv)
			return true
		}
	default:
		//其他类型
		if sv.Type().String() == vv.Type().String() {
			sv.Set(vv)
			return true
		} else {
			log.Println("paramter value:", sv.Type().String(), "map value:", vv.Type().String())
		}
	}

	return false
}

//指定Map指定关键字的值
func (this *Int64Map) Set(key int64, value interface{}) {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.m[key] = value
	return
}

//删除Map中的一个值
func (this *Int64Map) Delete(key int64) {
	this.lock.Lock()
	defer this.lock.Unlock()
	delete(this.m, key)
}

//删除Map中的一个值
func (this *Int64Map) Remove(key int64) {
	this.lock.Lock()
	defer this.lock.Unlock()
	delete(this.m, key)
}

//获取Map中全部的关键字列表
func (this *Int64Map) Keys() []int64 {
	this.lock.RLock()
	defer this.lock.RUnlock()
	keys := make([]int64, 0, len(this.m))
	for key, _ := range this.m {
		keys = append(keys, key)
	}
	return keys
}

//获取Map中全部值列表
func (this *Int64Map) Values() []interface{} {
	this.lock.RLock()
	defer this.lock.RUnlock()
	vals := make([]interface{}, 0, len(this.m))
	for _, val := range this.m {
		vals = append(vals, val)
	}
	return vals
}

//获取Map中键值对列表
func (this *Int64Map) KeyValues() (keys []int64, vals []interface{}) {
	this.lock.RLock()
	defer this.lock.RUnlock()
	keys = make([]int64, 0, len(this.m))
	vals = make([]interface{}, 0, len(keys))
	for key, val := range this.m {
		keys = append(keys, key)
		vals = append(vals, val)
	}
	return
}
